import { useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Image,
  KeyboardAvoidingView,
  Modal,
  Platform,
  Pressable,
  ScrollView,
  StyleSheet,
  TextInput,
  View,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import DateTimePicker from '@react-native-community/datetimepicker';
import { ResizeMode, Video } from 'expo-av';
import { useLocalSearchParams, useRouter } from 'expo-router';

import { ThemedButton } from '@/components/themed-button';
import { IconButton } from '@/components/icon-button';
import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { ZoomImageModal } from '@/components/zoom-image-modal';
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { useTranslation } from '@/localization/i18n';
import { dbPromise, initCoreTables } from '@/services/db';

const CATEGORY_PRESETS = ['seed', 'fertilizer', 'labor', 'fuel', 'equipment', 'transport', 'misc'];

type FieldRow = {
  id: number;
  name: string | null;
};

type CropRow = {
  id: number;
  crop_name: string | null;
};

type CostRow = {
  id: number;
  field_id: number | null;
  crop_id: number | null;
  category: string | null;
  amount: number | null;
  currency: string | null;
  vendor: string | null;
  notes: string | null;
  spent_at: string | null;
  photo_uri: string | null;
};

type MediaRow = {
  uri: string | null;
};

export default function CostDetailScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const { id } = useLocalSearchParams<{ id?: string | string[] }>();
  const costId = Number(Array.isArray(id) ? id[0] : id);
  const theme = useColorScheme() ?? 'light';
  const palette = Colors[theme];

  const [loading, setLoading] = useState(true);
  const [status, setStatus] = useState('');
  const [fields, setFields] = useState<FieldRow[]>([]);
  const [crops, setCrops] = useState<CropRow[]>([]);
  const [currency, setCurrency] = useState('THB');
  const [fieldModalOpen, setFieldModalOpen] = useState(false);
  const [cropModalOpen, setCropModalOpen] = useState(false);
  const [selectedFieldId, setSelectedFieldId] = useState<number | null>(null);
  const [selectedCropId, setSelectedCropId] = useState<number | null>(null);
  const [category, setCategory] = useState('');
  const [amount, setAmount] = useState('');
  const [vendor, setVendor] = useState('');
  const [notes, setNotes] = useState('');
  const [spentDate, setSpentDate] = useState('');
  const [showSpentPicker, setShowSpentPicker] = useState(false);
  const [mediaUris, setMediaUris] = useState<string[]>([]);
  const [activeUri, setActiveUri] = useState<string | null>(null);
  const [errors, setErrors] = useState<{ field?: string; amount?: string }>({});
  const [zoomUri, setZoomUri] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [showSaved, setShowSaved] = useState(false);

  useEffect(() => {
    let isActive = true;

    async function loadCost() {
      try {
        await initCoreTables();
        const db = await dbPromise;
        const fieldRows = await db.getAllAsync<FieldRow>('SELECT id, name FROM fields ORDER BY name ASC;');
        const cropRows = await db.getAllAsync<CropRow>('SELECT id, crop_name FROM crops ORDER BY crop_name ASC;');
        const profileRow = await db.getFirstAsync<{ currency: string | null }>(
          'SELECT currency FROM user_profile WHERE id = 1;'
        );
        const rows = await db.getAllAsync<CostRow>(
          `SELECT id, field_id, crop_id, category, amount, currency, vendor, notes, spent_at, photo_uri
           FROM costs WHERE id = ? LIMIT 1;`,
          costId
        );
        if (!isActive) return;
        setFields(fieldRows);
        setCrops(cropRows);
        setCurrency(profileRow?.currency ?? 'THB');
        const cost = rows[0];
        if (!cost) {
          setStatus(t('costs.empty'));
          setLoading(false);
          return;
        }
        setSelectedFieldId(cost.field_id ?? null);
        setSelectedCropId(cost.crop_id ?? null);
        setCategory(cost.category ?? '');
        setAmount(cost.amount !== null ? String(cost.amount) : '');
        setVendor(cost.vendor ?? '');
        setNotes(cost.notes ?? '');
        setSpentDate(cost.spent_at ?? '');
        const mediaRows = await db.getAllAsync<MediaRow>(
          'SELECT uri FROM cost_media WHERE cost_id = ? ORDER BY created_at ASC;',
          costId
        );
        const media = uniqueMediaUris([
          ...mediaRows.map((row) => row.uri).filter(Boolean),
          ...(normalizeMediaUri(cost.photo_uri) ? [normalizeMediaUri(cost.photo_uri) as string] : []),
        ] as string[]);
        setMediaUris(media);
        setActiveUri(media[0] ?? normalizeMediaUri(cost.photo_uri));
      } catch (error) {
        if (isActive) setStatus(`Error: ${String(error)}`);
      } finally {
        if (isActive) setLoading(false);
      }
    }

    loadCost();
    return () => {
      isActive = false;
    };
  }, [costId, t]);

  const selectedField = useMemo(
    () => fields.find((item) => item.id === selectedFieldId),
    [fields, selectedFieldId]
  );
  const selectedCrop = useMemo(
    () => crops.find((item) => item.id === selectedCropId),
    [crops, selectedCropId]
  );

  const inputStyle = [
    styles.input,
    {
      borderColor: palette.border,
      backgroundColor: palette.input,
      color: palette.text,
    },
  ];

  async function handleUpdate() {
    const parsedAmount = amount.trim() ? Number(amount) : null;
    const nextErrors: { field?: string; amount?: string } = {};
    if (!selectedFieldId) nextErrors.field = t('costs.fieldRequired');
    if (!parsedAmount || !Number.isFinite(parsedAmount)) nextErrors.amount = t('costs.amountInvalid');
    setErrors(nextErrors);
    if (Object.keys(nextErrors).length > 0) return;
    try {
      setSaving(true);
      const db = await dbPromise;
      const primaryUri = mediaUris[0] ?? normalizeMediaUri(activeUri);
      await db.runAsync(
        'UPDATE costs SET field_id = ?, crop_id = ?, category = ?, amount = ?, currency = ?, vendor = ?, notes = ?, spent_at = ?, photo_uri = ? WHERE id = ?;',
        selectedFieldId,
        selectedCropId,
        category.trim() || null,
        parsedAmount,
        currency,
        vendor.trim() || null,
        notes.trim() || null,
        spentDate || null,
        primaryUri ?? null,
        costId
      );
      await db.runAsync('DELETE FROM cost_media WHERE cost_id = ?;', costId);
      const now = new Date().toISOString();
      const mediaToInsert = uniqueMediaUris([
        ...mediaUris,
        ...(normalizeMediaUri(activeUri) ? [normalizeMediaUri(activeUri) as string] : []),
      ]);
      for (const uri of mediaToInsert) {
        await db.runAsync(
          'INSERT INTO cost_media (cost_id, uri, media_type, created_at) VALUES (?, ?, ?, ?);',
          costId,
          uri,
          isVideoUri(uri) ? 'video' : 'image',
          now
        );
      }
      setStatus(t('costs.saved'));
      setShowSaved(true);
      setTimeout(() => {
        setShowSaved(false);
        setStatus('');
      }, 1800);
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete() {
    Alert.alert(t('costs.deleteTitle'), t('costs.deleteMessage'), [
      { text: t('costs.cancel'), style: 'cancel' },
      {
        text: t('costs.delete'),
        style: 'destructive',
        onPress: async () => {
          const db = await dbPromise;
          await db.runAsync('DELETE FROM costs WHERE id = ?;', costId);
          router.back();
        },
      },
    ]);
  }

  if (loading) {
    return (
      <ThemedView style={[styles.container, { backgroundColor: palette.background, padding: 16 }]}>
        <ThemedText>{t('costs.loading')}</ThemedText>
      </ThemedView>
    );
  }

  return (
    <ThemedView style={[styles.container, { backgroundColor: palette.background }]}>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        style={styles.keyboardAvoid}>
        <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
          <ThemedText type="title">{t('costs.edit')}</ThemedText>
          {status && !showSaved ? <ThemedText>{status}</ThemedText> : null}

          <ThemedText>
            {t('costs.field')}
            <ThemedText style={styles.requiredMark}> *</ThemedText>
          </ThemedText>
          <ThemedButton
            title={selectedField?.name || t('costs.selectField')}
            onPress={() => setFieldModalOpen(true)}
            variant="secondary"
          />
          {errors.field ? <ThemedText style={styles.errorText}>{errors.field}</ThemedText> : null}

          <ThemedText>{t('costs.crop')}</ThemedText>
          <ThemedButton
            title={selectedCrop?.crop_name || t('costs.selectCrop')}
            onPress={() => setCropModalOpen(true)}
            variant="secondary"
          />

          <ThemedText>{t('costs.category')}</ThemedText>
          <View style={styles.chipRow}>
            {CATEGORY_PRESETS.map((preset) => {
              const label = t(`costs.category.${preset}`);
              const isActive = label === category || preset === category;
              return (
                <Pressable
                  key={preset}
                  style={[styles.chip, isActive ? styles.chipActive : null]}
                  onPress={() => setCategory(label)}>
                  <ThemedText style={styles.chipText}>{label}</ThemedText>
                </Pressable>
              );
            })}
          </View>
          <TextInput
            value={category}
            onChangeText={setCategory}
            placeholder={t('costs.categoryPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
          />

          <ThemedText>
            {t('costs.amount')} ({currency})
            <ThemedText style={styles.requiredMark}> *</ThemedText>
          </ThemedText>
          <TextInput
            value={amount}
            onChangeText={(value) => {
              setAmount(value);
              if (errors.amount) setErrors((prev) => ({ ...prev, amount: undefined }));
            }}
            placeholder={t('costs.amountPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
            keyboardType="decimal-pad"
          />
          {errors.amount ? <ThemedText style={styles.errorText}>{errors.amount}</ThemedText> : null}

          <ThemedText>{t('costs.vendor')}</ThemedText>
          <TextInput
            value={vendor}
            onChangeText={setVendor}
            placeholder={t('costs.vendorPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
          />

          <ThemedText>{t('costs.date')}</ThemedText>
          <Pressable onPress={() => setShowSpentPicker(true)} style={styles.dateInput}>
            <ThemedText style={styles.dateValue}>
              {spentDate || t('costs.datePlaceholder')}
            </ThemedText>
          </Pressable>
          {showSpentPicker ? (
            <DateTimePicker
              value={spentDate ? new Date(spentDate) : new Date()}
              mode="date"
              onChange={(event, date) => {
                setShowSpentPicker(false);
                if (date) setSpentDate(toDateOnly(date));
              }}
            />
          ) : null}

          <ThemedText>{t('costs.notes')}</ThemedText>
          <TextInput
            value={notes}
            onChangeText={setNotes}
            placeholder={t('costs.notesPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={[inputStyle, styles.multiline]}
            multiline
          />

          <ThemedText>{t('costs.addMedia')}</ThemedText>
          {normalizeMediaUri(activeUri) ? (
            isVideoUri(normalizeMediaUri(activeUri) as string) ? (
              <Video
                source={{ uri: normalizeMediaUri(activeUri) as string }}
                style={styles.mediaPreview}
                useNativeControls
                resizeMode={ResizeMode.CONTAIN}
              />
            ) : (
              <Pressable onPress={() => setZoomUri(normalizeMediaUri(activeUri) as string)}>
                <Image source={{ uri: normalizeMediaUri(activeUri) as string }} style={styles.mediaPreview} resizeMode="contain" />
              </Pressable>
            )
          ) : (
            <ThemedView style={[styles.mediaPlaceholder, { borderColor: palette.border }]}>
              <ThemedText style={styles.mediaPlaceholderText}>{t('costs.noPhoto')}</ThemedText>
            </ThemedView>
          )}
          {mediaUris.length > 0 ? (
            <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.mediaRow}>
              {mediaUris.map((uri) => (
                <Pressable
                  key={uri}
                  style={styles.mediaThumbWrap}
                  onPress={() => setActiveUri(uri)}>
                  {isVideoUri(uri) ? (
                    <Video
                      source={{ uri }}
                      style={styles.mediaThumb}
                      resizeMode={ResizeMode.COVER}
                      isMuted
                    />
                  ) : (
                    <Image source={{ uri }} style={styles.mediaThumb} resizeMode="cover" />
                  )}
                  <Pressable
                    style={styles.mediaRemove}
                    onPress={() => {
                      setMediaUris((prev) => {
                        const next = prev.filter((item) => item !== uri);
                        if (activeUri === uri) setActiveUri(next[0] ?? null);
                        return next;
                      });
                    }}>
                    <ThemedText style={styles.mediaRemoveText}>×</ThemedText>
                  </Pressable>
                </Pressable>
              ))}
            </ScrollView>
          ) : null}

          <View style={styles.mediaButtons}>
            <ThemedButton
              title={t('costs.pickFromGallery')}
              onPress={() =>
                handlePickMedia((uris) => {
                  setMediaUris((prev) => uniqueMediaUris([...prev, ...uris]));
                  if (!activeUri && uris[0]) setActiveUri(uris[0]);
                })
              }
              variant="secondary"
            />
            <ThemedButton
              title={t('costs.takeMedia')}
              onPress={() =>
                handleTakeMedia((uri) => {
                  if (!uri) return;
                  setMediaUris((prev) => uniqueMediaUris([...prev, uri]));
                  if (!activeUri) setActiveUri(uri);
                })
              }
              variant="secondary"
            />
          </View>

          <View style={styles.actions}>
            <IconButton
              name="trash"
              onPress={handleDelete}
              accessibilityLabel={t('costs.delete')}
              variant="danger"
            />
            <View style={styles.updateGroup}>
              {showSaved ? <ThemedText style={[styles.inlineToastText, { color: palette.success }]}>{t('costs.saved')}</ThemedText> : null}
              <ThemedButton
                title={saving ? t('costs.saving') : t('costs.update')}
                onPress={handleUpdate}
              />
            </View>
          </View>
        </ScrollView>
      </KeyboardAvoidingView>

      <Modal transparent visible={fieldModalOpen} animationType="fade">
        <Pressable style={styles.modalOverlay} onPress={() => setFieldModalOpen(false)}>
          <View style={[styles.modalCard, { backgroundColor: palette.card, borderColor: palette.border }]}>
            <ThemedText type="subtitle">{t('costs.selectField')}</ThemedText>
            <ScrollView>
              {fields.map((item) => (
                <Pressable
                  key={item.id}
                  onPress={() => {
                    setSelectedFieldId(item.id);
                    setErrors((prev) => ({ ...prev, field: undefined }));
                    setFieldModalOpen(false);
                  }}
                  style={styles.modalItem}>
                  <ThemedText>{item.name || t('costs.untitled')}</ThemedText>
                </Pressable>
              ))}
            </ScrollView>
          </View>
        </Pressable>
      </Modal>

      <Modal transparent visible={cropModalOpen} animationType="fade">
        <Pressable style={styles.modalOverlay} onPress={() => setCropModalOpen(false)}>
          <View style={[styles.modalCard, { backgroundColor: palette.card, borderColor: palette.border }]}>
            <ThemedText type="subtitle">{t('costs.selectCrop')}</ThemedText>
            <ScrollView>
              {crops.map((item) => (
                <Pressable
                  key={item.id}
                  onPress={() => {
                    setSelectedCropId(item.id);
                    setCropModalOpen(false);
                  }}
                  style={styles.modalItem}>
                  <ThemedText>{item.crop_name || t('costs.untitled')}</ThemedText>
                </Pressable>
              ))}
            </ScrollView>
          </View>
        </Pressable>
      </Modal>

      <ZoomImageModal visible={Boolean(zoomUri)} uri={zoomUri} onClose={() => setZoomUri(null)} />
    </ThemedView>
  );
}

async function handlePickMedia(onAdd: (uris: string[]) => void) {
  const pickerTypes =
    (ImagePicker as { MediaType?: { Images?: string; Videos?: string } }).MediaType ??
    (ImagePicker as { MediaTypeOptions?: { Images?: string; Videos?: string } }).MediaTypeOptions ??
    undefined;
  const mediaTypes =
    pickerTypes?.Images && pickerTypes?.Videos
      ? [pickerTypes.Images.toLowerCase(), pickerTypes.Videos.toLowerCase()]
      : ['images', 'videos'];
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes,
    quality: 1,
    allowsMultipleSelection: true,
  });
  if (result.canceled) return;
  const uris = result.assets.map((asset) => asset.uri).filter(Boolean);
  if (uris.length > 0) onAdd(uris);
}

async function handleTakeMedia(onAdd: (uri: string | null) => void) {
  const pickerTypes =
    (ImagePicker as { MediaType?: { Images?: string; Videos?: string } }).MediaType ??
    (ImagePicker as { MediaTypeOptions?: { Images?: string; Videos?: string } }).MediaTypeOptions ??
    undefined;
  const mediaTypes =
    pickerTypes?.Images && pickerTypes?.Videos
      ? [pickerTypes.Images.toLowerCase(), pickerTypes.Videos.toLowerCase()]
      : ['images', 'videos'];
  const result = await ImagePicker.launchCameraAsync({
    mediaTypes,
    quality: 1,
  });
  if (result.canceled) return;
  onAdd(result.assets[0]?.uri ?? null);
}

function isVideoUri(uri: string) {
  const cleaned = uri.split('?')[0]?.toLowerCase() ?? '';
  return ['.mp4', '.mov', '.m4v', '.webm', '.mkv', '.avi'].some((ext) => cleaned.endsWith(ext));
}

function normalizeMediaUri(uri?: string | null) {
  if (!uri) return null;
  if (uri.startsWith('file://') || uri.startsWith('http://') || uri.startsWith('https://')) return uri;
  return `file://${uri}`;
}

function uniqueMediaUris(uris: string[]) {
  return Array.from(new Set(uris.filter(Boolean)));
}

function toDateOnly(date: Date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  keyboardAvoid: { flex: 1 },
  content: { padding: 16, paddingBottom: 40 },
  input: {
    borderWidth: 1,
    borderRadius: 12,
    paddingHorizontal: 12,
    paddingVertical: 10,
    marginTop: 6,
    marginBottom: 12,
    fontSize: 16,
  },
  multiline: { minHeight: 90, textAlignVertical: 'top' },
  errorText: { color: '#C0392B', marginBottom: 8 },
  requiredMark: { color: '#C0392B' },
  dateInput: {
    borderWidth: 1,
    borderRadius: 12,
    paddingHorizontal: 12,
    paddingVertical: 12,
    marginTop: 6,
    marginBottom: 12,
  },
  dateValue: { fontSize: 16 },
  chipRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, marginBottom: 8 },
  chip: {
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 999,
    borderWidth: 1,
    borderColor: '#C9D2C4',
    backgroundColor: '#F8F6F0',
  },
  chipActive: { backgroundColor: '#DDE8DA', borderColor: '#88A68F' },
  chipText: { fontSize: 13 },
  mediaPreview: {
    width: '100%',
    height: 200,
    borderRadius: 16,
    backgroundColor: '#F1F1F1',
    marginBottom: 12,
  },
  mediaPlaceholder: {
    width: '100%',
    height: 200,
    borderRadius: 16,
    borderWidth: 1,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: 12,
  },
  mediaPlaceholderText: { opacity: 0.7 },
  mediaRow: { marginBottom: 12 },
  mediaThumbWrap: { marginRight: 8 },
  mediaThumb: { width: 72, height: 72, borderRadius: 12 },
  mediaRemove: {
    position: 'absolute',
    top: -6,
    right: -6,
    width: 22,
    height: 22,
    borderRadius: 11,
    backgroundColor: '#2C2C2C',
    justifyContent: 'center',
    alignItems: 'center',
  },
  mediaRemoveText: { color: '#fff', fontSize: 14, lineHeight: 16 },
  updateGroup: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  inlineToastText: {
    fontWeight: '700',
    fontSize: 12,
  },
  mediaButtons: { flexDirection: 'row', gap: 12, flexWrap: 'wrap', marginBottom: 16 },
  actions: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8 },
  modalOverlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.4)',
    justifyContent: 'center',
    padding: 20,
  },
  modalCard: {
    borderRadius: 16,
    borderWidth: 1,
    padding: 16,
    maxHeight: '70%',
  },
  modalItem: { paddingVertical: 10 },
});
